/*
** $Id: lobject.h,v 2.117.1.1 2017/04/19 17:39:34 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/


#ifndef lobject_h
#define lobject_h


#include <stdarg.h>


#include "llimits.h"
#include "lua.h"


/*
** Extra tags for non-values
*/
#define LUA_TPROTO  LUA_NUMTAGS    /* function prototypes */
#define LUA_TDEADKEY  (LUA_NUMTAGS+1)    /* removed keys in tables */

/*
** number of all possible tags (including LUA_TNONE but excluding DEADKEY)
*/
#define LUA_TOTALTAGS  (LUA_TPROTO + 2)


/*
** tags for Tagged Values have the following use of bits:
** bits 0-3: actual tag (a LUA_T* value)
** bits 4-5: variant bits
** bit 6: whether value is collectable
*/


/*
** LUA_TFUNCTION variants:
** 0 - Lua function
** 1 - light C function
** 2 - regular C function (closure)
*/

/* Variant tags for functions */
/**
 * @file
 * @brief Lua函数类型的宏定义
 *
 * 这些宏定义了Lua中不同类型的函数标记，用于区分Lua闭包、轻量级C函数和C闭包。
 *
 * - `LUA_TLCL`: Lua闭包（Lua closure），表示一个Lua函数及其关联的闭包环境。
 * - `LUA_TLCF`: 轻量级C函数（light C function），表示一个简单的C函数，没有闭包环境。
 * - `LUA_TCCL`: C闭包（C closure），表示一个C函数及其关联的闭包环境。
 *
 * 这些宏通过位掩码的方式组合了`LUA_TFUNCTION`类型和额外的标志位来区分不同的函数类型。
 */
#define LUA_TLCL  (LUA_TFUNCTION | (0 << 4))  /* Lua closure */
#define LUA_TLCF  (LUA_TFUNCTION | (1 << 4))  /* light C function */
#define LUA_TCCL  (LUA_TFUNCTION | (2 << 4))  /* C closure */


/* Variant tags for strings */
#define LUA_TSHRSTR  (LUA_TSTRING | (0 << 4))  /* short strings */
#define LUA_TLNGSTR  (LUA_TSTRING | (1 << 4))  /* long strings */


/* Variant tags for numbers */
#define LUA_TNUMFLT  (LUA_TNUMBER | (0 << 4))  /* float numbers */
#define LUA_TNUMINT  (LUA_TNUMBER | (1 << 4))  /* integer numbers */

/**
 * 标记位，用于标识可回收类型（collectable types）。
 * 该宏定义了一个位标记，用于在类型系统中标识哪些类型是可回收的（例如需要垃圾回收的类型）。
 * 使用位移操作（1 << 6）确保该标记位不会与其他位冲突。
 */
/* Bit mark for collectable types */
#define BIT_ISCOLLECTABLE (1 << 6)

/* mark a tag as collectable */
#define ctb(t)      ((t) | BIT_ISCOLLECTABLE)


/*
** Common type for all collectable objects
*/
typedef struct GCObject GCObject;


/**
 * 通用头部宏定义，用于所有可收集对象（以宏形式定义，供其他对象包含）。
 * 包含以下字段：
 * - next: 指向下一个 GCObject 的指针，用于垃圾回收链表的连接。
 * - tt: 对象的类型标记（lu_byte 类型）。
 * - marked: 对象的标记状态（lu_byte 类型），用于垃圾回收过程中的标记阶段。
 */
/*
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
*/
#define CommonHeader  GCObject *next; lu_byte tt; lu_byte marked


/*
** Common type has only the common header
*/
struct GCObject {
    CommonHeader;
};




/*
** Tagged Values. This is the basic representation of values in Lua,
** an actual value plus a tag with its type.
*/

/**
 * Lua 值的联合体，用于存储 Lua 中的所有可能值类型。
 * 该联合体支持多种类型的值，包括可回收对象、轻量级用户数据、布尔值、轻量级 C 函数、整数和浮点数。
 * 各字段说明：
 * - gc: 指向可回收对象（GCObject）的指针。
 * - p: 轻量级用户数据的指针。
 * - b: 布尔值（通常为 0 或 1）。
 * - f: 轻量级 C 函数的指针。
 * - i: Lua 整数类型（lua_Integer）。
 * - n: Lua 浮点数类型（lua_Number）。
 */
/*
** Union of all Lua values
*/
typedef union Value {
    GCObject *gc;    /* collectable objects */
    void *p;         /* light userdata */
    int b;           /* booleans */
    lua_CFunction f; /* light C functions */
    lua_Integer i;   /* integer numbers */
    lua_Number n;    /* float numbers */
} Value;


#define TValuefields  Value value_; int tt_


typedef struct lua_TValue {
    TValuefields;
} TValue;



/* macro defining a nil value */
#define NILCONSTANT  {NULL}, LUA_TNIL


#define val_(o)    ((o)->value_)


/* raw type tag of a TValue */
#define rttype(o) ((o)->tt_)

/**
 * 定义一个宏，用于提取给定值的低4位（即无变体标记）。
 * 该宏通过位掩码操作（0x0F）来清除高4位，仅保留低4位。
 * 通常用于处理无变体的标记值。
 */
/* tag with no variants (bits 0-3) */
#define novariant(x) ((x) & 0x0F)

/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
#define ttype(o) (rttype(o) & 0x3F)

/**
 * 获取 TValue 的类型标签（无变体，位 0-3）。
 * @param o 输入的 TValue 对象。
 * @return 返回 TValue 的类型标签（无变体部分）。
 */
/* type tag of a TValue with no variants (bits 0-3) */
#define ttnov(o) (novariant(rttype(o)))

/* Macros to test type */
#define checktag(o, t)    (rttype(o) == (t))
#define checktype(o, t)    (ttnov(o) == (t))
#define ttisnumber(o)    checktype((o), LUA_TNUMBER)
#define ttisfloat(o)    checktag((o), LUA_TNUMFLT)
#define ttisinteger(o)    checktag((o), LUA_TNUMINT)
#define ttisnil(o)    checktag((o), LUA_TNIL)
#define ttisboolean(o)    checktag((o), LUA_TBOOLEAN)
#define ttislightuserdata(o)  checktag((o), LUA_TLIGHTUSERDATA)
#define ttisstring(o)    checktype((o), LUA_TSTRING)
#define ttisshrstring(o)  checktag((o), ctb(LUA_TSHRSTR))
#define ttislngstring(o)  checktag((o), ctb(LUA_TLNGSTR))
#define ttistable(o)    checktag((o), ctb(LUA_TTABLE))
#define ttisfunction(o)    checktype(o, LUA_TFUNCTION)
#define ttisclosure(o)    ((rttype(o) & 0x1F) == LUA_TFUNCTION)
#define ttisCclosure(o)    checktag((o), ctb(LUA_TCCL))
#define ttisLclosure(o)    checktag((o), ctb(LUA_TLCL))
#define ttislcf(o)    checktag((o), LUA_TLCF)
#define ttisfulluserdata(o)  checktag((o), ctb(LUA_TUSERDATA))
#define ttisthread(o)    checktag((o), ctb(LUA_TTHREAD))
#define ttisdeadkey(o)    checktag((o), LUA_TDEADKEY)


/* Macros to access values */
#define ivalue(o)  check_exp(ttisinteger(o), val_(o).i)
#define fltvalue(o)  check_exp(ttisfloat(o), val_(o).n)
#define nvalue(o)  check_exp(ttisnumber(o), \
  (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))
#define gcvalue(o)  check_exp(iscollectable(o), val_(o).gc)
#define pvalue(o)  check_exp(ttislightuserdata(o), val_(o).p)
#define tsvalue(o)  check_exp(ttisstring(o), gco2ts(val_(o).gc))
#define uvalue(o)  check_exp(ttisfulluserdata(o), gco2u(val_(o).gc))
#define clvalue(o)  check_exp(ttisclosure(o), gco2cl(val_(o).gc))
#define clLvalue(o)  check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
#define clCvalue(o)  check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
#define fvalue(o)  check_exp(ttislcf(o), val_(o).f)
#define hvalue(o)  check_exp(ttistable(o), gco2t(val_(o).gc))
#define bvalue(o)  check_exp(ttisboolean(o), val_(o).b)
#define thvalue(o)  check_exp(ttisthread(o), gco2th(val_(o).gc))
/* a dead value may get the 'gc' field, but cannot access its contents */
#define deadvalue(o)  check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))

#define l_isfalse(o)  (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))

/**
 * 检查给定的对象是否为可回收类型。
 * 通过检查对象的类型标志位是否包含 BIT_ISCOLLECTABLE 来判断。
 *
 * @param o 待检查的对象。
 * @return 如果对象是可回收类型，则返回真（非零值）；否则返回假（零）。
 */
#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE)

/**
 * @brief 检查对象是否为正确的类型（内部测试用宏）。
 * @param obj 待检查的对象。
 * @return 如果对象的类型与垃圾回收值的类型一致，则返回真（非零值），否则返回假（零）。
 * @note 此宏用于内部测试，不推荐在外部代码中使用。
 */
/* Macros for internal tests */
#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt)

#define checkliveness(L, obj) \
  lua_longassert(!iscollectable(obj) || \
    (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)))))


/* Macros to set values */
#define settt_(o, t)  ((o)->tt_=(t))

#define setfltvalue(obj, x) \
  { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }

#define chgfltvalue(obj, x) \
  { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); }

#define setivalue(obj, x) \
  { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }

#define chgivalue(obj, x) \
  { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }

#define setnilvalue(obj) settt_(obj, LUA_TNIL)

#define setfvalue(obj, x) \
  { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); }

/**
 * setpvalue 是一个宏，用于设置一个 TValue 类型的值（Lua 中的一个值）的指针部分，并指定其类型。
 * obj 是一个指向 TValue 的指针。
 * x 是要赋给 obj 的指针值。
 * TValue *io=(obj); 将 obj 指针赋给局部变量 io。
 * val_(io).p=(x); 将 x 的值赋给 io 指向的 TValue 的指针部分。
 * settt_(io, LUA_TLIGHTUSERDATA); 设置 io 指向的 TValue 的类型标记为 LUA_TLIGHTUSERDATA，表示这是一个轻量级用户数据类型。
 */
/**
 * 设置一个轻量级用户数据（light userdata）到给定的 TValue 对象中。
 *
 * @param obj 指向 TValue 对象的指针，用于存储用户数据。
 * @param x 要存储的轻量级用户数据指针。
 *
 * 注意：
 * - 该宏用于快速设置轻量级用户数据，不涉及内存分配或引用计数。
 * - 设置后，TValue 的类型标记为 LUA_TLIGHTUSERDATA。
 */
#define setpvalue(obj, x)           \
  {                                 \
    TValue *io = (obj);             \
    val_(io).p = (x);               \
    settt_(io, LUA_TLIGHTUSERDATA); \
  }

#define setbvalue(obj, x)     \
  {                           \
    TValue *io = (obj);       \
    val_(io).b = (x);         \
    settt_(io, LUA_TBOOLEAN); \
  }

/**
 * 设置 Lua 对象的值为一个垃圾回收对象（GCObject）。
 *
 * @param L Lua 状态机（未直接使用，但保留以保持一致性）。
 * @param obj 指向目标 TValue 的指针，用于存储 GCObject。
 * @param x 要设置的 GCObject 指针。
 *
 * @note 这是一个宏定义，用于高效地操作 Lua 对象的内部值。
 *       它会将 `obj` 的值设置为 `x`，并更新其类型标记为 `x` 的类型。
 */
#define setgcovalue(L, obj, x) \
  {                            \
    TValue *io = (obj);        \
    GCObject *i_g = (x);       \
    val_(io).gc = i_g;         \
    settt_(io, ctb(i_g->tt));  \
  }

/**
 * 设置一个字符串值到给定的对象中。
 *
 * @param L Lua状态机指针。
 * @param obj 目标对象，用于存储字符串值。
 * @param x 要设置的字符串值。
 *
 * 该宏将字符串值 `x` 存储到对象 `obj` 中，并更新其类型标记。
 * 同时会检查对象的活跃性（liveness）。
 */
#define setsvalue(L, obj, x)   \
  {                            \
    TValue *io = (obj);        \
    TString *x_ = (x);         \
    val_(io).gc = obj2gco(x_); \
    settt_(io, ctb(x_->tt));   \
    checkliveness(L, io);      \
  }

#define setuvalue(L, obj, x) \
  { TValue *io = (obj); Udata *x_ = (x); \
    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
    checkliveness(L,io); }

#define setthvalue(L, obj, x) \
  { TValue *io = (obj); lua_State *x_ = (x); \
    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
    checkliveness(L,io); }

/***
这段代码是一个宏定义，用于在 Lua 虚拟机中设置一个 `TValue`（Lua 中的一个值的表示）为一个闭包（即一个包含环境的函数）。宏 `setclLvalue` 接收三个参数：`L`，`obj` 和 `x`。下面是对宏中每个部分的解释：

1. `#define setclLvalue(L, obj, x)`：这是宏定义的开始，`setclLvalue` 是宏的名称，它接受三个参数：`L`、`obj` 和 `x`。

2. `{ ... }`：宏定义中的代码块，用于执行一系列操作。

3. `TValue *io = (obj);`：声明一个指向 `TValue` 的指针 `io` 并将其初始化为 `obj` 的值。`obj` 是一个 `TValue` 类型的值，这里通过类型转换确保 `io` 是一个 `TValue` 指针。

4. `LClosure *x_ = (x);`：声明一个指向 `LClosure`（Lua 中的一个闭包结构）的指针 `x_` 并将其初始化为 `x` 的值。`x` 是一个闭包，这里通过类型转换确保 `x_` 是一个 `LClosure` 指针。

5. `val_(io).gc = obj2gco(x_);`：在这个表达式中，`val_(io).gc` 访问 `io` 指向的 `TValue` 的 `gc`（垃圾收集器）字段，并将 `x_` 转换为一个 `GCObject` 指针（通过调用 `obj2gco` 函数），然后赋值给 `gc`。`GCObject` 是 Lua 中用于垃圾收集的对象的基类。

6. `settt_(io, ctb(LUA_TLCL));`：这个表达式设置了 `io` 指向的 `TValue` 的类型。`ctb(LUA_TLCL)` 调用 `ctb` 函数（可能是一个宏或内联函数）来获取 `LUA_TLCL`（Lua 闭包标记）的标记值。`settt_` 函数（可能是一个宏或内联函数）用于设置 `TValue` 的类型字段。

7. `checkliveness(L,io);`：调用 `checkliveness` 函数，传递 Lua 状态 `L` 和 `TValue` 指针 `io`。这个函数可能用于检查 `io` 指向的对象是否是活动的，即是否应该被考虑在垃圾收集过程中。

宏 `setclLvalue` 的总体作用是将一个 `TValue` 设置为指向一个 Lua 闭包的值，并确保类型信息正确设置，同时检查闭包的活跃状态。这在 Lua 的实现中用于操作 Lua 栈上的值，尤其是在创建和操作闭包时。

请注意，由于宏中使用了未在问题中定义的函数和宏（如 `val_`、`obj2gco`、`ctb`、`settt_` 和 `checkliveness`），因此这些函数和宏的具体实现和行为可能会根据 Lua 的内部实现有所不同。上述解释基于宏定义的常见模式和 C 语言的语法规则。
 */
#define setclLvalue(L, obj, x) \
  { TValue *io = (obj); LClosure *x_ = (x); \
    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
    checkliveness(L,io); }

#define setclCvalue(L, obj, x) \
  { TValue *io = (obj); CClosure *x_ = (x); \
    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \
    checkliveness(L,io); }

#define sethvalue(L, obj, x)     \
  {                              \
    TValue *io = (obj);          \
    Table *x_ = (x);             \
    val_(io).gc = obj2gco(x_);   \
    settt_(io, ctb(LUA_TTABLE)); \
    checkliveness(L, io);        \
  }

/**
 * 将对象标记为“死亡键”（LUA_TDEADKEY）。
 * 该宏用于标记一个对象为无效键，通常在垃圾回收过程中使用。
 *
 * @param obj 需要标记的对象。
 */
#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)

/**
 * 用于将一个 TValue 类型的值（Lua 中的一个值）复制到另一个 TValue 类型的值中。
 * 宏定义接收三个参数：L 是指向 lua_State 结构体的指针，代表当前的 Lua 状态；obj1 是目标 TValue 指针；obj2 是源 TValue 指针。
 * #define setobj(L, obj1, obj2)：这是宏定义的开始，setobj 是宏的名称，它接受三个参数：L，obj1，和 obj2。
 *   {：开始一个复合语句。
 *     TValue *io1=(obj1);：声明一个指向 TValue 的指针 io1 并初始化为 obj1 的值。
 *     *io1 = *(obj2);：将 obj2 指向的 TValue 的值复制给 io1 指向的 TValue。这是实际的赋值操作，使用间接引用操作符 * 来获取指针指向的值，并进行复制。
 *     (void)L;：这是一个未使用的语句，用来避免编译器警告。(void) 将 L 的值强制转换为 void 类型，从而抑制可能产生的未使用参数的警告。
 *     checkliveness(L,io1);：调用 checkliveness 函数，传入当前的 Lua 状态 L 和目标 TValue 指针 io1。
 *        checkliveness 函数可能用于检查 io1 是否是一个活动的引用，即它是否指向一个有效的、当前可达的对象。这个检查对于垃圾收集和内存管理是重要的。
 *   }：结束复合语句。
 * 宏 setobj 的作用是简化赋值操作，并且确保在赋值后进行了活跃性检查。
 *    在 Lua 的实现中，这个宏可能用于复制值，尤其是在处理 Lua 栈或者 Lua 表时，确保赋值后的对象是活跃的，对垃圾收集器可见。
 */
#define setobj(L, obj1, obj2) \
  { TValue *io1=(obj1); *io1 = *(obj2); \
    (void)L; checkliveness(L,io1); }


/*
** different types of assignments, according to destination
*/

/* from stack to (same) stack */
#define setobjs2s  setobj
/* to stack (not from same stack) */
#define setobj2s  setobj
#define setsvalue2s  setsvalue
#define sethvalue2s  sethvalue
#define setptvalue2s  setptvalue
/* from table to same table */
#define setobjt2t  setobj
/* to new object */
#define setobj2n  setobj
#define setsvalue2n  setsvalue

/* to table (define it as an expression to be used in macros) */
#define setobj2t(L, o1, o2)  ((void)L, *(o1)=*(o2), checkliveness(L,(o1)))


/*
** {======================================================
** types and prototypes
** =======================================================
*/


typedef TValue *StkId;  /* index to stack elements */




/**
 * TString 结构体：用于表示 Lua 中的字符串值。
 *
 * 字符串的字节数据紧跟在结构体之后（根据 UTString 对齐）。
 *
 * 字段说明：
 * - CommonHeader: 通用头部，用于垃圾回收等机制。
 * - extra: 保留字段，短字符串用于标记保留字，长字符串用于标记是否已计算哈希值。
 * - shrlen: 短字符串的长度。
 * - hash: 字符串的哈希值。
 * - u: 联合体，根据字符串类型存储不同数据：
 *   - lnglen: 长字符串的长度。
 *   - hnext: 哈希表中用于链接下一个字符串的指针。
 */
/*
** Header for string value; string bytes follow the end of this structure
** (aligned according to 'UTString'; see next).
*/
typedef struct TString {
    CommonHeader;
    lu_byte extra;  /* reserved words for short strings; "has hash" for longs */
    lu_byte shrlen;  /* length for short strings */
    unsigned int hash;
    union {
        size_t lnglen;  /* length for long strings */
        struct TString *hnext;  /* linked list for hash table */
    } u;
} TString;


/**
 * 确保此类型之后的地址始终完全对齐。
 * 使用联合体 UTString 来保证字符串的最大对齐。
 * - dummy: 用于确保字符串的最大对齐。
 * - tsv: 实际的字符串结构体。
 */
/*
** Ensures that address after this type is always fully aligned.
*/
typedef union UTString {
    L_Umaxalign dummy;  /* ensures maximum alignment for strings */
    TString tsv;
} UTString;


/**
 * 从 'TString' 结构中获取实际的字符串（字节数组）。
 * 通过访问 'extra' 字段确保值确实是一个 'TString'。
 */
/*
** Get the actual string (array of bytes) from a 'TString'.
** (Access to 'extra' ensures that value is really a 'TString'.)
*/
#define getstr(ts)  \
  check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString))


/* get the actual string (array of bytes) from a Lua value */
#define svalue(o)       getstr(tsvalue(o))

/* get string length from 'TString *s' */
#define tsslen(s)  ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen)

/* get string length from 'TValue *o' */
#define vslen(o)  tsslen(tsvalue(o))


/*
** Header for userdata; memory area follows the end of this structure
** (aligned according to 'UUdata'; see next).
*/
typedef struct Udata {
    CommonHeader;
    lu_byte ttuv_;  /* user value's tag */
    struct Table *metatable;
    size_t len;  /* number of bytes */
    union Value user_;  /* user value */
} Udata;


/*
** Ensures that address after this type is always fully aligned.
*/
typedef union UUdata {
    L_Umaxalign dummy;  /* ensures maximum alignment for 'local' udata */
    Udata uv;
} UUdata;


/*
**  Get the address of memory block inside 'Udata'.
** (Access to 'ttuv_' ensures that value is really a 'Udata'.)
*/
#define getudatamem(u)  \
  check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata)))

#define setuservalue(L, u, o) \
  { const TValue *io=(o); Udata *iu = (u); \
    iu->user_ = io->value_; iu->ttuv_ = rttype(io); \
    checkliveness(L,io); }


#define getuservalue(L, u, o) \
  { TValue *io=(o); const Udata *iu = (u); \
    io->value_ = iu->user_; settt_(io, iu->ttuv_); \
    checkliveness(L,io); }


/*
** Description of an upvalue for function prototypes
*/
typedef struct Upvaldesc {
    TString *name;  /* upvalue name (for debug information) */
    lu_byte instack;  /* whether it is in stack (register) */
    lu_byte idx;  /* index of upvalue (in stack or in outer function's list) */
} Upvaldesc;


/*
** Description of a local variable for function prototypes
** (used for debug information)
 * 它在 Lua 函数原型中用于描述局部变量，通常用于调试信息。
 * LocVar 结构体包含了局部变量的名称、其生效的起始指令位置以及结束指令位置，
 * 这些信息有助于调试器跟踪局部变量的作用域和生命周期。
*/
typedef struct LocVar {
    TString *varname;
    int startpc;  /* first point where variable is active */
    int endpc;    /* first point where variable is dead */
} LocVar;

/*
** Function Prototypes
*/
/**
 * 表示 Lua 函数原型的结构体，包含函数的所有静态信息。
 *
 * @field numparams        固定参数的数量。
 * @field is_vararg        是否为可变参数函数（1 表示是，0 表示否）。
 * @field maxstacksize     函数执行时需要的寄存器数量。
 * @field sizeupvalues     上值（upvalues）的数量。
 * @field sizek            常量表（k）的大小。
 * @field sizecode         指令（code）的数量。
 * @field sizelineinfo     行号信息（lineinfo）的大小。
 * @field sizep            内部函数（p）的数量。
 * @field sizelocvars      局部变量信息（locvars）的数量。
 * @field linedefined      函数定义的起始行号（调试信息）。
 * @field lastlinedefined  函数定义的结束行号（调试信息）。
 * @field k                函数使用的常量表（TValue 数组）。
 * @field code             函数的指令集（操作码 + 操作数）。
 * @field p                函数内部定义的子函数原型（Proto 数组）。
 * @field lineinfo         指令到源代码行号的映射（调试信息）。
 * @field locvars          局部变量的信息（调试信息）。
 * @field upvalues         上值的信息。
 * @field cache            最近创建的闭包（LClosure）缓存。
 * @field source           源代码字符串（调试信息）。
 * @field gclist           垃圾回收链表。
 */
typedef struct Proto
{
  CommonHeader;
  lu_byte numparams; /* number of fixed parameters */
  lu_byte is_vararg;
  lu_byte maxstacksize; /* number of registers needed by this function */
  int sizeupvalues;     /* size of 'upvalues' */
  int sizek;            /* size of 'k' */
  int sizecode;
  int sizelineinfo;
  int sizep; /* size of 'p' */
  int sizelocvars;
  int linedefined;        /* debug information  */
  int lastlinedefined;    /* debug information  */
  TValue *k;              /* constants used by the function 常量*/
  Instruction *code;      /* opcodes 指令（操作码+操作数）*/
  struct Proto **p;       /* functions defined inside the function */
  int *lineinfo;          /* map from opcodes to source lines (debug information) */
  LocVar *locvars;        /* information about local variables (debug information) */
  Upvaldesc *upvalues;    /* upvalue information */
  struct LClosure *cache; /* last-created closure with this prototype */
  TString *source;        /* used for debug information */
  GCObject *gclist;
} Proto;

/*
** Lua Upvalues
*/
typedef struct UpVal UpVal;


/*
** Closures
*/

#define ClosureHeader \
  CommonHeader;       \
  lu_byte nupvalues;  \
  GCObject *gclist

/**
 * CClosure 结构体表示一个 C 语言闭包。
 * 它包含以下成员：
 * - ClosureHeader: 闭包的头部信息。
 * - f: 指向 C 函数的指针，表示闭包的实际执行逻辑。
 * - upvalue: 一个 TValue 数组，用于存储闭包的 upvalue（捕获的外部变量）。
 */
typedef struct CClosure
{
  ClosureHeader;
  lua_CFunction f;
  TValue upvalue[1]; /* list of upvalues */
} CClosure;

/**
 * LClosure 结构体表示 Lua 中的闭包（closure）。
 * 闭包是 Lua 中函数和其关联的 upvalue 的组合。
 *
 * @field ClosureHeader 闭包的通用头部信息。
 * @field p 指向 Proto 结构体的指针，表示闭包关联的函数原型。
 * @field upvals 一个数组，存储闭包引用的 upvalue（上值）列表。
 *               upvals[1] 表示数组的起始位置，实际大小可能动态扩展。
 */
typedef struct LClosure
{
  ClosureHeader;
  struct Proto *p;
  UpVal *upvals[1]; /* list of upvalues */
} LClosure;

/**
 * @brief 联合体 Closure，用于表示 Lua 中的闭包。
 *
 * 该联合体可以表示两种类型的闭包：
 * - CClosure (c): C 语言实现的闭包。
 * - LClosure (l): Lua 语言实现的闭包。
 *
 * 通过联合体的特性，可以灵活地处理不同类型的闭包。
 */
typedef union Closure
{
  CClosure c;
  LClosure l;
} Closure;

#define isLfunction(o)  ttisLclosure(o)

#define getproto(o)  (clLvalue(o)->p)

/*
** Tables
*/
/**
 * TKey 是一个联合体，用于表示 Lua 表中的键。
 * 它包含两种可能的表示形式：
 * 1. `nk` 结构体：包含一个 TValuefields 和一个 `next` 字段，用于链式存储（表示下一个节点的偏移量）。
 * 2. `tvk`：一个 TValue 类型的值，直接存储键的值。
 *
 * 这种设计允许灵活地处理不同类型的键，同时支持链式存储以解决哈希冲突。
 */

typedef union TKey
{
  struct
  {
    TValuefields;
    int next; /* for chaining (offset for next node) */
  } nk;
  TValue tvk;
} TKey;

/* copy a value into a key without messing up field 'next' */
#define setnodekey(L, key, obj) \
  { TKey *k_=(key); const TValue *io_=(obj); \
    k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \
    (void)L; checkliveness(L,io_); }

/**
 * @brief 表示一个键值对节点。
 *
 * 该结构体用于存储一个键值对，其中：
 * - `i_val` 是节点的值部分。
 * - `i_key` 是节点的键部分。
 *
 * 通常用于哈希表、字典或其他需要键值对存储的场景。
 */
typedef struct Node
{
  TValue i_val;
  TKey i_key;
} Node;

/**
 * @struct Table
 * @brief Lua中的表结构，用于表示Lua中的表（table）类型。
 *
 * @var CommonHeader
 * 公共头部，用于垃圾回收和类型标记。
 *
 * @var lu_byte flags
 * 标志位，用于标记表的元方法是否存在。1<<p 表示元方法 tagmethod(p) 不存在。
 *
 * @var lu_byte lsizenode
 * 哈希部分的大小，以2为底的对数形式存储。
 *
 * @var unsigned int sizearray
 * 数组部分的大小。
 *
 * @var TValue *array
 * 指向数组部分的指针，存储连续索引的值。
 *
 * @var Node *node
 * 指向哈希部分的指针，存储键值对。
 *
 * @var Node *lastfree
 * 指向哈希部分中最后一个空闲位置之前的指针。
 *
 * @var struct Table *metatable
 * 指向元表的指针，用于定义表的元方法。
 *
 * @var GCObject *gclist
 * 用于垃圾回收的链表指针。
 */
typedef struct Table
{
  CommonHeader;
  lu_byte flags;          /* 1<<p means tagmethod(p) is not present */
  lu_byte lsizenode;      /* log2 of size of 'node' array */
  unsigned int sizearray; /* size of 'array' array */
  TValue *array;          /* array part */
  Node *node;
  Node *lastfree; /* any free position is before this position */
  struct Table *metatable;
  GCObject *gclist;
} Table;

/*
** 'module' operation for hashing (size is always a power of 2)
 * 取模计算，用于获取 s 对 size 的模（相除的余数）
*/
#define lmod(s, size) \
  (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))


#define twoto(x)  (1<<(x))
// 例如，如果 t->lsizenode 的值是 3，那么 sizenode(t) 的结果是 8
#define sizenode(t)  (twoto((t)->lsizenode))


/*
** (address of) a fixed nil value
*/
#define luaO_nilobject    (&luaO_nilobject_)


LUAI_DDEC const TValue luaO_nilobject_;

/* size of buffer for 'luaO_utf8esc' function */
#define UTF8BUFFSZ  8

LUAI_FUNC int luaO_int2fb(unsigned int x);

LUAI_FUNC int luaO_fb2int(int x);

LUAI_FUNC int luaO_utf8esc(char *buff, unsigned long x);

LUAI_FUNC int luaO_ceillog2(unsigned int x);

LUAI_FUNC void luaO_arith(lua_State *L, int op, const TValue *p1,
                          const TValue *p2, TValue *res);

LUAI_FUNC size_t luaO_str2num(const char *s, TValue *o);

LUAI_FUNC int luaO_hexavalue(int c);

LUAI_FUNC void luaO_tostring(lua_State *L, StkId obj);

LUAI_FUNC const char *luaO_pushvfstring(lua_State *L, const char *fmt,
                                        va_list argp);

LUAI_FUNC const char *luaO_pushfstring(lua_State *L, const char *fmt, ...);

LUAI_FUNC void luaO_chunkid(char *out, const char *source, size_t len);


#endif

